package com.yuqih.common.dto;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class FieldDescriptor {

	private String fieldName;
	private Field field;
	private Method readMethod;
	private Method writeMethod;
	private Class<?> fieldType;
	private Class<?> itemType;

	private final Map<Class<?>, Annotation> annotationsMapping = new HashMap<Class<?>, Annotation>();

	FieldDescriptor() {
		super();
	}

	/**
	 * @return the fieldName
	 */
	public String getFieldName() {
		return fieldName;
	}

	/**
	 * @return the field
	 */
	public Field getField() {
		return field;
	}

	/**
	 * @return the readMethod
	 */
	public Method getReadMethod() {
		return readMethod;
	}

	/**
	 * @return the writeMethod
	 */
	public Method getWriteMethod() {
		return writeMethod;
	}

	/**
	 * @return the fieldType
	 */
	public Class<?> getFieldType() {
		return fieldType;
	}

	/**
	 * @return the itemType
	 */
	public Class<?> getItemType() {
		return itemType;
	}

	@SuppressWarnings("unchecked")
	public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
		if (annotationsMapping.containsKey(annotationClass)) {
			return (T) annotationsMapping.get(annotationClass);
		}

		T annotation = field.getAnnotation(annotationClass);
		if (annotation != null) {
			annotationsMapping.put(annotationClass, annotation);
			return annotation;
		}
		annotation = readMethod.getAnnotation(annotationClass);
		if (annotation != null) {
			annotationsMapping.put(annotationClass, annotation);
			return annotation;
		}
		annotation = writeMethod.getAnnotation(annotationClass);
		if (annotation != null) {
			annotationsMapping.put(annotationClass, annotation);
			return annotation;
		}
		return null;
	}

	/**
	 * @param fieldName
	 *            the fieldName to set
	 */
	void setFieldName(String fieldName) {
		this.fieldName = fieldName;
	}

	/**
	 * @param field
	 *            the field to set
	 */
	void setField(Field field) {
		this.field = field;
	}

	/**
	 * @param readMethod
	 *            the readMethod to set
	 */
	void setReadMethod(Method readMethod) {
		this.readMethod = readMethod;
	}

	/**
	 * @param writeMethod
	 *            the writeMethod to set
	 */
	void setWriteMethod(Method writeMethod) {
		this.writeMethod = writeMethod;
	}

	/**
	 * @param fieldType
	 *            the fieldType to set
	 */
	void setFieldType(Class<?> fieldType) {
		this.fieldType = fieldType;
	}

	/**
	 * @param itemType
	 *            the itemType to set
	 */
	void setItemType(Class<?> itemType) {
		this.itemType = itemType;
	}

}
